package com.lovegu.two;

import javafx.application.Application;
import javafx.geometry.Bounds;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.*;
import java.util.stream.Collectors;


/**
 * <p>
 * 使用 JavaFx 实现生成简单的中文词云
 * </p>
 *
 * @author 老顾
 * @since 2023/3/31
 */
public class WordCloudCloudExample extends Application {
    private static final int WIDTH = 800;
    private static final int HEIGHT = 600;
    private static final int MAX_FONT_SIZE = 60;
    private static final int MIN_FONT_SIZE = 10;
    private static final int MAX_WORDS = 100;

    @Override
    public void start(Stage primaryStage) throws Exception {
        // 读取文本文件
        File file = new File("src/main/resources/input.txt");
        BufferedReader reader = new BufferedReader(new FileReader(file));
        String line;
        List<String> words = new ArrayList<>();
        while ((line = reader.readLine()) != null) {
            words.addAll(Arrays.asList(line.split("\\s+")));
        }
        reader.close();

        // 统计词频
        Map<String, Integer> freqMap = new HashMap<>();
        for (String word : words) {
            freqMap.put(word, freqMap.getOrDefault(word, 0) + 1);
        }

        // 按词频排序
        List<Map.Entry<String, Integer>> sortedFreqList = freqMap.entrySet().stream()
                .sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
                .limit(MAX_WORDS)
                .collect(Collectors.toList());

        // 计算字体大小
        int maxFreq = sortedFreqList.get(0).getValue();
        int minFreq = sortedFreqList.get(sortedFreqList.size() - 1).getValue();
        double sizeRatio = (MAX_FONT_SIZE - MIN_FONT_SIZE) * 1.0 / (maxFreq - minFreq);
        Map<String, Integer> sizeMap = new HashMap<>();
        for (Map.Entry<String, Integer> entry : sortedFreqList) {
            int freq = entry.getValue();
            int size = (int) (MIN_FONT_SIZE + (freq - minFreq) * sizeRatio);
            sizeMap.put(entry.getKey(), size);
        }

        // 创建词云
        Pane root = new Pane();
        root.setPrefSize(WIDTH, HEIGHT);
        Random random = new Random();
        for (Map.Entry<String, Integer> entry : sortedFreqList) {
            String word = entry.getKey();
            int size = sizeMap.get(word);
            Text text = new Text(word);
            text.setFont(Font.font(size));
            text.setFill(Color.rgb(random.nextInt(256), random.nextInt(256), random.nextInt(256)));
            root.getChildren().add(text);
        }

        // 防止重叠
        List<Text> textList = root.getChildren().stream()
                .filter(node -> node instanceof Text)
                .map(node -> (Text) node)
                .collect(Collectors.toList());
        for (int i = 0; i < textList.size(); i++) {
            Text text1 = textList.get(i);
            Bounds bounds1 = text1.getBoundsInParent();
            for (int j = i + 1; j < textList.size(); j++) {
                Text text2 = textList.get(j);
                Bounds bounds2 = text2.getBoundsInParent();
                if (bounds1.intersects(bounds2)) {
                    double dx = bounds2.getMinX() - bounds1.getMaxX();
                    double dy = bounds2.getMinY() - bounds1.getMaxY();
                    text2.setTranslateX(text2.getTranslateX() - dx);
                    text2.setTranslateY(text2.getTranslateY() - dy);
                }
            }
        }

        // 调整位置
        double centerX = WIDTH / 2.0;
        double centerY = HEIGHT / 2.0;
        for (Text text : textList) {
            Bounds bounds = text.getBoundsInParent();
            double x = random.nextDouble() * (WIDTH - bounds.getWidth());
            double y = random.nextDouble() * (HEIGHT - bounds.getHeight());
            text.setTranslateX(x - bounds.getMinX());
            text.setTranslateY(y - bounds.getMinY());
        }

        // 显示窗口
        Scene scene = new Scene(new Group(root), WIDTH, HEIGHT);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}